package online.chazi.bootplus.autoconfiguation.multiple.datasource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import online.chazi.bootplus.autoconfiguation.multiple.datasource.aspect.DataSourceAdvisor;
import online.chazi.bootplus.autoconfiguation.multiple.datasource.aspect.DataSourceInterceptor;
import online.chazi.bootplus.multiple.datasource.BalanceDataSourceProperties;
import online.chazi.bootplus.multiple.datasource.MultipleDataSource;
import online.chazi.bootplus.multiple.datasource.MultipleDataSourceProperties;
import online.chazi.bootplus.multiple.datasource.router.MultipleDataSourceBalanceRouter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 说明：作者很懒，什么都没留下
 * Created by 叉子同学 on 2020-05-12 15:18
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(MultipleDataSourceProperties.class)
public class MultipleDataSourceConfig {

    @Bean
    public MultipleDataSource multipleDataSource(MultipleDataSourceProperties multipleDataSourceProperties) throws IllegalAccessException, InstantiationException {
        MultipleDataSource multipleDataSource = new MultipleDataSource(multipleDataSourceProperties.getPrimary(), (MultipleDataSourceBalanceRouter) multipleDataSourceProperties.getLoadBalanceRouter().newInstance());
        Map<Object, Object> targetSources = new HashMap<>(); //Map<String, DataSource>
        for (BalanceDataSourceProperties properties : multipleDataSourceProperties.getSources()) {
            DataSource dataSource;
            if (properties.getType() == com.zaxxer.hikari.HikariDataSource.class && properties.getHikari() != null) {
                HikariConfig hikariConfig = properties.getHikari();
                hikariConfig.setJdbcUrl(properties.getUrl());
                hikariConfig.setUsername(properties.getUsername());
                hikariConfig.setPassword(properties.getPassword());
                hikariConfig.setDriverClassName(properties.getDriverClassName());
                dataSource = new HikariDataSource(hikariConfig);
                log.debug("创建HikariDataSource:{}", properties.getHikari());
            } else {
                dataSource = DataSourceBuilder.create()
                        .type(properties.getType())
                        .url(properties.getUrl())
                        .username(properties.getUsername())
                        .password(properties.getPassword())
                        .driverClassName(properties.getDriverClassName())
                        .build();
                log.debug("创建datasource, type={}", properties.getType());
            }
            targetSources.put(properties.getName(), dataSource);

            //设置默认数据源，primary
            if (properties.getName().equals(multipleDataSourceProperties.getPrimary())) {
                multipleDataSource.setDefaultTargetDataSource(dataSource);
            }

            //group分组，实现负载均衡
            if (properties.getName().contains(MultipleDataSource.GROUP_SEPARATOR)) {
                Integer weight = properties.getBalanceWeight();
                multipleDataSource.addGroupDataSource(properties.getName(), weight == null ? 1 : weight);
            }

        }
        multipleDataSource.setTargetDataSources(targetSources);
        return multipleDataSource;
    }

    @Bean
    @ConditionalOnMissingBean
    public DataSourceAdvisor dataSourceAdvisor() {
        return new DataSourceAdvisor(new DataSourceInterceptor());
    }

}
